﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using Universe.OneC.DomainModel;

namespace Universe.OneC
{
    public partial class OneCReader
    {
        private PropertyValue GetPropertyValue(object value, ObjectsCache objects)
        {
            PropertyValue propertyValue;

            // NULL?
            if (value == null || value == DBNull.Value)
            {
                PrimitivePropertyValue ppv = new PrimitivePropertyValue(null);
                propertyValue = ppv;
            }

            // Примитивный тип?
            else if (!Marshal.IsComObject(value))
            {
                PrimitivePropertyValue ppv = new PrimitivePropertyValue(value);
                propertyValue = ppv;
            }

            else
            {
                // Ссылка на 1С-экземпляр
                bool? isEmpty = null;
                try
                {
                    object rawIsEmpty = value.Call("IsEmpty");
                    if (rawIsEmpty is bool)
                        isEmpty = (bool?)rawIsEmpty;
                }
                catch
                {
                    // нет метода IsEmpty()
                }

                string fullName = null;
                try
                {
                    object vm = value.Call("Metadata");
                    fullName = (string)vm.Call("FullName");
                    vm.ReleaseComObject();
                }
                catch
                {
                }

                string[] nameParts =
                    string.IsNullOrEmpty(fullName)
                        ? new string[0]
                        : fullName.Split('.');

                if (nameParts.Length == 2 && nameParts[0] == "Перечисление")
                {
                    PropertyOfEnumRef per;
                    if (isEmpty.HasValue && !isEmpty.Value)
                    {
                        int? enumIndex = null;
                        MetaEnumValue enumValue = null;

                        string enumName = nameParts[1];
                        string manName = "EnumManager." + enumName;
                        object man = objects.GetObject(manName);
                        int ei = (int)man.Call("IndexOf", value);
                        enumIndex = ei;

                        MetaClass ec = Model.Registry[Model.Name + ".Перечисления." + enumName];
                        enumValue = ec.EnumValues[ei];

                        per = new PropertyOfEnumRef(ei, enumValue);
                        per.HasValue = true;
                    }
                    else
                    {
                        per = new PropertyOfEnumRef(-1, null);
                        per.HasValue = false;
                    }

                    per.Type1C = fullName;
                    propertyValue = per;
                }

                else if (nameParts.Length == 2 && nameParts[0] == "Справочник")
                {
                    PropertyOfCatalogRef pcf;
                    if (isEmpty.HasValue && !isEmpty.Value)
                    {
                        /* это документ
                                        object number = value.Get("Number");
                                        DateTime date = (DateTime) value.Get("Date");
                                        bool deletionMark = (bool) value.Get("DeletionMark");
                                        bool posted = (bool) value.Get("Posted");
                                         */

                        object code = value.Get("Code");
                        string description = (string)value.Get("Description");
                        bool deletionMark = (bool)value.Get("DeletionMark");
                        bool predefined = (bool)value.Get("Predefined");
                        bool isFolder = (bool)value.Get("IsFolder");

                        object @ref = value.Get("Ref");
                        object uuid = @ref.Call("UUID");
                        string uuidString = (string)this.Adapter.GlobalMethod("XMLString", uuid);
                        @uuid.ReleaseComObject();
                        @ref.ReleaseComObject();


                        pcf = new PropertyOfCatalogRef
                        {
                            Code = new IdInstance(code),
                            DeletionMark = deletionMark,
                            Description = description,
                            IsFolder = isFolder,
                            Uid = new Guid(uuidString),
                            Predefined = predefined,
                            HasValue = true,
                            Type1C = fullName
                        };
                    }
                    else
                    {
                        pcf = new PropertyOfCatalogRef
                        {
                            Code = null,
                            HasValue = false,
                            Type1C = fullName
                        };
                    }

                    propertyValue = pcf;
                }

                else if (nameParts.Length == 2 && nameParts[0] == "Документ")
                {
                    PropertyOfDocumentRef pcf;
                    if (isEmpty.HasValue && !isEmpty.Value)
                    {
                        object number = value.Get("Number");
                        DateTime date = (DateTime)value.Get("Date");
                        bool deletionMark = (bool)value.Get("DeletionMark");
                        bool posted = (bool)value.Get("Posted");


                        object @ref = value.Get("Ref");
                        object uuid = @ref.Call("UUID");
                        string uuidString = (string)this.Adapter.GlobalMethod("XMLString", uuid);
                        @uuid.ReleaseComObject();
                        @ref.ReleaseComObject();


                        pcf = new PropertyOfDocumentRef
                        {
                            Uid = new Guid(uuidString),
                            HasValue = true,
                            Type1C = fullName,
                            DeletionMark = deletionMark,

                            Number = new IdInstance(number),
                            Date = date,
                            Posted = posted,
                        };
                    }
                    else
                    {
                        pcf = new PropertyOfDocumentRef
                        {
                            Number = null,
                            HasValue = false,
                            Type1C = fullName
                        };
                    }

                    propertyValue = pcf;
                }

                else if (nameParts.Length == 2 && nameParts[0] == "ПланВидовРасчета")
                {
                    PropertyOfCalculationRef pcf;
                    if (isEmpty.HasValue && !isEmpty.Value)
                    {
                        object code = value.Get("Code");
                        string description = (string) value.Get("Description");
                        bool deletionMark = (bool)value.Get("DeletionMark");


                        object @ref = value.Get("Ref");
                        object uuid = @ref.Call("UUID");
                        string uuidString = (string)this.Adapter.GlobalMethod("XMLString", uuid);
                        @uuid.ReleaseComObject();
                        @ref.ReleaseComObject();


                        pcf = new PropertyOfCalculationRef
                        {
                            Uid = new Guid(uuidString),
                            Code = new IdInstance(code),
                            Description = description,

                            HasValue = true,
                            Type1C = fullName,
                            DeletionMark = deletionMark,

                        };
                    }
                    else
                    {
                        pcf = new PropertyOfCalculationRef
                        {
                            Code = null,
                            HasValue = false,
                            Type1C = fullName
                        };
                    }

                    propertyValue = pcf;
                }

                else
                {
                    propertyValue = new UnknownPropertyValue
                    {
                        HasValue = isEmpty.HasValue && !isEmpty.Value,
                        Type1C = fullName
                    };
                }
            }
            return propertyValue;
        }

    }
}
